﻿#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

//2.funcPointer函数名，其实是代表函数的入口地址；
void funcPointer()
{
	printf("1.输出Hello World!\n");
}
int arr[10];
int myFuncPointer(int a, char b)
{
	printf("5.输出自定义的函数：int myFunc(int a, char b) ！\n");
	return 0;
}
int con1(int a, int b)
{
	return a + b;
}
int con2(int a, int b)
{
	return a + b + 10;
}
int con3(int a, int b)
{
	return a + b - 10;
}
int con4(int a, int b)
{
	return a * b - 10;
}
int con5(int a, int b)
{
	return a + b - 3 + 100 * 2;
}
//13.函数con1可以作为另一个函数的参数，函数指针int(*pFuncCon)(int, int)做函数参数；
void doLogic(int(*pFuncCon)(int, int))
{
	int a = 30;
	int b = 40;
	int ret = pFuncCon(a, b);
	printf("12.输出doLogic函数的结果ret为：%d\n", ret);
}
void funcArray1()
{
	printf("15.函数指针数组的参数funcArray1；\n");
}
void funcArray2()
{
	printf("16.函数指针数组的参数funcArray2；\n");
}
void funcArray3()
{
	printf("17.函数指针数组的参数funcArray3；\n");
}
//18.函数指针做函数参数，回调函数；数组首地址arr，数组中每个元素的长度eleSize，数组长度len；
//void printAllArray(void* arr, int eleSize, int len)
//void printAllArray(void* arr, int eleSize, int len, void(*print)(void*))

//24.直接定义函数指针类型；
typedef void(*print_type)(void*);
void printAllArray(void* arr, int eleSize, int len, print_type print)
{
	char* start = (char*)arr;
	for (int i = 0; i < len; ++i)
	{
		printf("19.输出数组中的每个元素的地址：%d\n", start + i * eleSize);
		//11204620 11204624 ... 11204636 --> 11204260 11204328 ... 11204532
		//print(start + i * eleSize);
		char* eleAddr = start + i * eleSize;
		print(eleAddr);
	}
}
//23.C语言不支持函数重载，C语言中的函数名不能相同；
void myPrint(void* data)
{
	int* p = (int*)data;
	printf("21.输出数组中每个元素地址指向的值*p：%d\n", *p);
}
struct PersonFuncP
{
	char name[64];
	int age;
};
void myPrintPerson(void* data)
{
	struct PersonFuncP* person = (struct PersonFuncP*)data;
	printf("22.输出结构体数组persons中每个元素结构体person的Name：%s  Age：%d\n", person->name, person->age);
}
//3.决定函数的类型，应该是：函数的返回值，函数的参数列表；
void testFuncPointer()
{
	//4.定义一个指向函数的指针；
	//6.定义函数类型，通过类型来定义函数指针；
	typedef int(FUN_TYPE)(int, char);
	FUN_TYPE* pFunc = myFuncPointer;

	pFunc(10, 'a');//5.输出自定义的函数：int myFunc(int a, char b) ！
	(*pFunc)(20, 'b');//5.输出自定义的函数：int myFunc(int a, char b) ！
	myFuncPointer(30, 'c');//5.输出自定义的函数：int myFunc(int a, char b) ！

	//7.直接定义函数指针类型；
	typedef int(*FUN_P)(int, char);
	FUN_P pFunc2 = myFuncPointer;
	pFunc2(40, 'd');//5.输出自定义的函数：int myFunc(int a, char b) ！

	//8.函数指针指向同类型；直接报错，因为FUN_P的参数和funcPointer参数不同，不能这样指向；
	//pFunc2 = funcPointer;

	//9.直接定义函数指针变量；
	//int(*pFunc3)(int, char) = NULL;
	//11.把指针转换为函数指针类型写法；(int(*)(int, char))0x001
	int(*pFunc3)(int, char) = (int(*)(int, char))NULL;
	pFunc3 = myFuncPointer;
	pFunc3(50, 'e');//5.输出自定义的函数：int myFunc(int a, char b) ！
	printf("10.输出函数指针变量pFunc3的内存大小：%d\n", sizeof(pFunc3));//4

	//int(*pFuncCon)(int, int) = con1;
	//int(*pFuncCon)(int, int) = con2;
	//int(*pFuncCon)(int, int) = con3;
	int(*pFuncCon)(int, int) = con4;
	int ret = pFuncCon(10, 20);
	printf("11.输出函数结构体变量pFuncCon指向函数con1，得到的值为：%d\n", ret);//30-->40-->20-->190

	doLogic(con1);//70
	doLogic(con5);//267

	//14.定义函数指针数组，返回值类型void，函数名func_array，参数个数3，函数参数()；
	void(*func_array[3])();
	func_array[0] = funcArray1;
	func_array[1] = funcArray2;
	func_array[2] = funcArray3;
	for (int i = 0; i < 3; ++i)
	{
		func_array[i]();//funcArray1；funcArray2；funcArray3；
	}

	int arr[] = { 1,2,3,4,5 };
	//printAllArray(arr, sizeof(int), 5);//15726484，...，15726500
	printAllArray(arr, sizeof(int), 5, myPrint);//1，...，5
	printf("------------------------------------------------------------\n");
	for (int i = 0; i < 5; ++i)
	{
		printf("20.输出数组arr中每个元素的地址：%d\n", &arr[i]);//15726484，...，15726500
	}


	struct PersonFuncP persons[] = {
		{"aaa",10},
		{"bbb",20},
		{"ccc",30},
		{"ddd",40},
		{"eee",50},
	};
	printAllArray(persons, sizeof(struct PersonFuncP), 5, myPrintPerson);//Name：aaa  Age：10，...，Name：eee  Age：50
}

//main213：函数指针
int main213()
{
	funcPointer();
	testFuncPointer();

	system("pause");
	return EXIT_SUCCESS;
}